package com.pucong.gitee.database.backup.configuration.jsonWeb;


import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.pucong.gitee.database.backup.business.sys.mapper.SysUserInfoMapper;
import com.pucong.gitee.database.backup.business.sys.service.SysLoginService;
import com.pucong.gitee.database.backup.common.entity.sys.SysReturnUrl;
import com.pucong.gitee.database.backup.common.entity.sys.SysUserInfo;
import com.pucong.gitee.database.backup.common.entity.sys.UserJwt;
import com.pucong.gitee.database.backup.common.entity.sys.jwt.CheckResult;
import com.pucong.gitee.database.backup.configuration.exception.BusinessException;
import com.pucong.gitee.database.backup.configuration.exception.BusinessExceptionService;
import com.pucong.gitee.database.backup.utils.JwtUtils;
import com.pucong.gitee.database.backup.utils.Res;
import com.pucong.gitee.database.backup.utils.Result;
import com.pucong.gitee.database.backup.utils.SystemConstant;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.Map;

/**
 * @author pucong
 */
@Component
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {

    private static Logger logger = LoggerFactory.getLogger(LoginInterceptor.class);

    @Autowired
    private BusinessExceptionService businessExceptionService;

    @Autowired
    private SysUserInfoMapper sysUserInfoMapper;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        String uri = request.getRequestURI();
        log.debug("进入拦截器preHandle,uri:"+uri);
        //从cookie中获取token
        String lsso_token = JwtUtils.getToken();

        // 拦截去登录
        if (null == lsso_token || "".equals(lsso_token)) {
            log.info("token为空，拦截去登录");
            SysReturnUrl url = new SysReturnUrl();
            url.setLssoUrl(SystemConstant.SYS_LOGIN_PATH);
            returnJson(response, SystemConstant.NO_LOGIN, "请先登录", url);
            return false;
        } else {
            // 校验token
            CheckResult checkResult = JwtUtils.validateJWT(lsso_token);
            if (checkResult.isSuccess()) {
                // 刷新token
                String refreshToken = JwtUtils.autoRefreshToken(checkResult, lsso_token);
                request.setAttribute(SystemConstant.JWT_TOKEN, refreshToken);
                // 获取用户信息
                String subject = checkResult.getClaims().getSubject();
                ObjectMapper objectMapper = new ObjectMapper();
                UserJwt loginUser = null;
                try {
                    loginUser = objectMapper.readValue(subject, UserJwt.class);
                } catch (JsonProcessingException e) {
                    throw new BusinessException("反序列化用户数据失败");
                }
                SysUserInfo sysUserInfo = sysUserInfoMapper.selectById(loginUser.getUuid());
                Date date = sysUserInfo.getLastLoginTime();
                if(date == null || date.getTime() != loginUser.getLastLoginTime().getTime()){
                    // token过期
                    SysReturnUrl url = new SysReturnUrl();
                    url.setLssoUrl(SystemConstant.SYS_LOGIN_PATH);
                    returnJson(response, SystemConstant.NO_LOGIN, "用户多次登录，请重新登录或修改密码", url);
                    return false;
                }
                loginUser.setToken(refreshToken);
                String userJson2 = objectMapper.writeValueAsString(loginUser);
                request.setAttribute(SystemConstant.REQUEST_USER_GET_NAME, userJson2);
                return true;
            } else {
                // token过期
                SysReturnUrl url = new SysReturnUrl();
                url.setLssoUrl(SystemConstant.SYS_LOGIN_PATH);
                if (checkResult.getErrCode().equals(SystemConstant.JWT_ERRCODE_EXPIRE)) {
                    returnJson(response, SystemConstant.NO_LOGIN, "token已过期，请先登录", url);
                } else {
                    returnJson(response, SystemConstant.NO_LOGIN, "token无效，请先登录", url);
                }
                return false;
            }
        }
    }


    private void returnJson(HttpServletResponse response, Integer code, String message, SysReturnUrl url) {
        PrintWriter writer = null;
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        try {
            writer = response.getWriter();
            Res res = Res.custom(code, message, url);
            ObjectMapper objectMapper = new ObjectMapper();
            String resStr = objectMapper.writeValueAsString(res);

            writer.print(resStr);
        } catch (IOException e) {
            log.error("拦截器输出流异常[{}]", e);
        } finally {
            if (writer != null) {
                writer.close();
            }
        }
    }

    private void response401(HttpServletResponse response) {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");

        try {
            String msg = businessExceptionService.getMessage("sys.common.notLogin");
            ObjectMapper mapper = new ObjectMapper();
            Res custom = Res.custom(Result.NO_LOGIN, msg);
            String json = mapper.writeValueAsString(custom);
            response.getWriter().print(json);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }

}
